package com.jsite.modules.flowable.utils;

import com.jsite.common.lang.StringUtils;
import com.jsite.common.lang.TimeUtils;
import com.jsite.modules.sys.entity.Role;
import com.jsite.modules.sys.entity.User;
import org.flowable.bpmn.model.*;
import org.flowable.common.engine.impl.de.odysseus.el.ExpressionFactoryImpl;
import org.flowable.common.engine.impl.de.odysseus.el.util.SimpleContext;
import org.flowable.common.engine.impl.javax.el.ExpressionFactory;
import org.flowable.common.engine.impl.javax.el.ValueExpression;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.idm.engine.impl.persistence.entity.GroupEntity;
import org.flowable.idm.engine.impl.persistence.entity.GroupEntityImpl;
import org.flowable.idm.engine.impl.persistence.entity.UserEntity;
import org.flowable.idm.engine.impl.persistence.entity.UserEntityImpl;
import org.flowable.task.api.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Map;

/**
 * 流程工具
 * @author liuruijun
 * @version 2018-08-03
 */
@Component
public class FlowableUtils {
	protected static Logger logger = LoggerFactory.getLogger(FlowableUtils.class);

	private static RuntimeService runtimeService;
	private static TaskService taskService;
	private static RepositoryService repositoryService;
	
	@Autowired
	private RuntimeService runtimeServiceIn;
	@Autowired
	private TaskService taskServiceIn;
	@Autowired
	private RepositoryService repositoryServiceIn;

	@PostConstruct
	public void init(){
		runtimeService = runtimeServiceIn;
		taskService = taskServiceIn;
		repositoryService = repositoryServiceIn;
	}

	public static UserEntity toFlowableUser(User user){
		if (user == null){
			return null;
		}
		UserEntity userEntity = new UserEntityImpl();
		userEntity.setId(user.getLoginName());
		userEntity.setFirstName(user.getName());
		userEntity.setLastName(StringUtils.EMPTY);
		userEntity.setPassword(user.getPassword());
		userEntity.setEmail(user.getEmail());
		userEntity.setRevision(1);
		return userEntity;
	}
	
	public static GroupEntity toFlowableGroup(Role role){
		if (role == null){
			return null;
		}
		GroupEntity groupEntity = new GroupEntityImpl();
		groupEntity.setId(role.getEnname());
		groupEntity.setName(role.getName());
		groupEntity.setType(role.getRoleType());
		groupEntity.setRevision(1);
		return groupEntity;
	}


	public static String toTimeString(long time) {
		TimeUtils t = new TimeUtils(time);
		int day = t.get(TimeUtils.DAY);
		int hour = t.get(TimeUtils.HOUR);
		int minute = t.get(TimeUtils.MINUTE);
		int second = t.get(TimeUtils.SECOND);
		StringBuilder sb = new StringBuilder();
		if (day > 0){
			sb.append(day).append("天");
		}
		if (hour > 0){
			sb.append(hour).append("时");
		}
		if (minute > 0){
			sb.append(minute).append("分");
		}
		if (second > 0){
			sb.append(second).append("秒");
		}
		return sb.toString();
	}


	// 判断下一节点是否有驳回
	public static boolean hasUnAuditPassFlow(String taskId) {
		if (StringUtils.isBlank(taskId)) {
			return true;
		}

		Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
		ExecutionEntity ee = (ExecutionEntity) runtimeService.createExecutionQuery().executionId(task.getExecutionId()).singleResult();

		// 当前审批节点
		String crruentActivityId = ee.getActivityId();
		BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
		FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(crruentActivityId);
		// 输出连线
		List<SequenceFlow> outFlows = flowNode.getOutgoingFlows();
		for (SequenceFlow sequenceFlow : outFlows) {
			// 下一个审批节点
			FlowElement targetFlow = sequenceFlow.getTargetFlowElement();
			if (targetFlow instanceof UserTask) {
				UserTask task1 = (UserTask) targetFlow;
				task1.getFormKey();
				logger.debug("下一节点: id=" + targetFlow.getId() + ",name=" + targetFlow.getName());
				return false;
			}
			// 如果下个审批节点为结束节点
			if (targetFlow instanceof EndEvent) {
				logger.debug("下一节点为结束节点：id=" + targetFlow.getId() + ",name=" + targetFlow.getName());
				return false;
			}

			if (targetFlow instanceof ExclusiveGateway) {
				logger.debug("下一节点为排他网关：id=" + targetFlow.getId() + ",name=" + targetFlow.getName());
				ExclusiveGateway gateway = (ExclusiveGateway) targetFlow;
				List<SequenceFlow> sequences = gateway.getOutgoingFlows();
				for (SequenceFlow flow : sequences) {
					if (flow.getConditionExpression().equals("${!auditPass}")) {
						return true;
					}
				}
			}
		}
		return false;
	}

	// 获取下一节点处理人
	public static String nextTaskAsignee(String procInsId, String taskId, Map<String, Object> variables) {
		if (StringUtils.isBlank(procInsId)) {// 开始节点，未选下一步处理人
			return "";
		}
		Map<String, Object> proVars = runtimeService.getVariables(procInsId);

		Task currTask = taskService.createTaskQuery().taskId(taskId).singleResult();
		ExecutionEntity ee = (ExecutionEntity) runtimeService.createExecutionQuery().executionId(currTask.getExecutionId()).singleResult();

		// 当前审批节点
		String crruentActivityId = ee.getActivityId();
		BpmnModel bpmnModel = repositoryService.getBpmnModel(currTask.getProcessDefinitionId());
		FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(crruentActivityId);

		List<SequenceFlow> outFlows = flowNode.getOutgoingFlows();
		for (SequenceFlow sequenceFlow : outFlows) {
			FlowElement targetFlow = sequenceFlow.getTargetFlowElement();
			if (targetFlow instanceof UserTask) {
				logger.debug("下一节点: id=" + targetFlow.getId() + ",name=" + targetFlow.getName());
				UserTask task = (UserTask) targetFlow;
				if (StringUtils.isBlank(task.getFormKey())) {
					return "";
				}
				Object asignee = proVars.get(task.getFormKey());

				return asignee == null?"":asignee.toString();
			}

			if (targetFlow instanceof EndEvent) {
				logger.debug("下一节点为结束节点：id=" + targetFlow.getId() + ",name=" + targetFlow.getName());
				return "end";
//				return (String) proVars.get("applyUserId");
			}

			if (targetFlow instanceof ExclusiveGateway) {
				logger.debug("下一节点为排他网关：id=" + targetFlow.getId() + ",name=" + targetFlow.getName());
				String regex = "(\\$|\\{|\\}|!|>|=|<|not|empty|\\d)";

				ExclusiveGateway gateway = (ExclusiveGateway) targetFlow;
				List<SequenceFlow> sequences = gateway.getOutgoingFlows();

				for (SequenceFlow flow : sequences) {
					String key = flow.getConditionExpression().replaceAll(regex, "").trim();
					Object var = variables.get(key)==null?"":variables.get(key);

					if (juel(key, var, flow.getConditionExpression())) {
						FlowElement targetEle = flow.getTargetFlowElement();
						if (targetEle instanceof EndEvent) {
							return "end";
//							return (String) proVars.get("applyUserId");
						}
						if (targetEle instanceof UserTask) {
							UserTask task  = (UserTask) flow.getTargetFlowElement();
							if (StringUtils.isBlank(task.getFormKey()) || task.getAssignee().contains("applyUserId")) {
//								return (String) proVars.get("applyUserId");
								return "";
							}
							Object asignee = proVars.get(task.getFormKey());

							return asignee == null?"":asignee.toString();
						}
					}
				}
			}
		}
		return "";
	}

	public static boolean juel(String key, Object var, String conditionExpression) {
		ExpressionFactory factory = new ExpressionFactoryImpl();
		SimpleContext context = new SimpleContext();
		if (var instanceof String) {
			context.setVariable(key, factory.createValueExpression(var, String.class));
		} else if (var instanceof  Boolean) {
			context.setVariable(key, factory.createValueExpression(var, Boolean.class));
		} else if (var instanceof Integer) {
			context.setVariable(key, factory.createValueExpression(var, Integer.class));
		}

		ValueExpression e = factory.createValueExpression(context, conditionExpression, Boolean.class);
		return (boolean) e.getValue(context);
	}
}
